﻿#include "MonitorDeviderWidget.h"
#include <QDebug>

MonitorDeviderWidget::MonitorDeviderWidget(QWidget *parent)
  : QWidget {parent}
  , mMode(DeviderMode::D4) {
    for(auto i = 0; i < 16; i++) {
        mItems.append(new MonitorDeviderItem(this));
    }
    mItems.at(0)->setSelected(true);
}

void MonitorDeviderWidget::resizeEvent(QResizeEvent *event) {
    // qDebug() << "resizeEvent";
    rebuild();
    QWidget::resizeEvent(event);
}

void MonitorDeviderWidget::rebuild() {
    auto strategy_d16 = [&]() {
        auto w = width() / 4;
        auto h = height() / 4;
        for(auto i = 0; i < mItems.size(); ++i) {
            auto item = mItems.at(i);
            switch(i) {
                case 0: item->setGeometry(0 * w, 0 * h, w, h); break;
                case 1: item->setGeometry(1 * w, 0 * h, w, h); break;
                case 2: item->setGeometry(2 * w, 0 * h, w, h); break;
                case 3: item->setGeometry(3 * w, 0 * h, w, h); break;
                case 4: item->setGeometry(0 * w, 1 * h, w, h); break;
                case 5: item->setGeometry(1 * w, 1 * h, w, h); break;
                case 6: item->setGeometry(2 * w, 1 * h, w, h); break;
                case 7: item->setGeometry(3 * w, 1 * h, w, h); break;
                case 8: item->setGeometry(0 * w, 2 * h, w, h); break;
                case 9: item->setGeometry(1 * w, 2 * h, w, h); break;
                case 10: item->setGeometry(2 * w, 2 * h, w, h); break;
                case 11: item->setGeometry(3 * w, 2 * h, w, h); break;
                case 12: item->setGeometry(0 * w, 3 * h, w, h); break;
                case 13: item->setGeometry(1 * w, 3 * h, w, h); break;
                case 14: item->setGeometry(2 * w, 3 * h, w, h); break;
                case 15: item->setGeometry(3 * w, 3 * h, w, h); break;
                default: break;
            }
        }
    };

    auto strategy_d13 = [&]() {
        auto w = width() / 4;
        auto h = height() / 4;
        for(auto i = 0; i < mItems.size(); ++i) {
            auto item = mItems.at(i);
            switch(i) {
                case 0: item->setGeometry(0 * w, 0 * h, w, h); break;
                case 1: item->setGeometry(1 * w, 0 * h, w, h); break;
                case 2: item->setGeometry(2 * w, 0 * h, w, h); break;
                case 3: item->setGeometry(3 * w, 0 * h, w, h); break;
                case 4: item->setGeometry(0 * w, 1 * h, w, h); break;
                case 5: item->setGeometry(1 * w, 1 * h, w * 2, h * 2); break;
                case 6: item->setVisible(false); break;
                case 7: item->setGeometry(3 * w, 1 * h, w, h); break;
                case 8: item->setGeometry(0 * w, 2 * h, w, h); break;
                case 9: item->setVisible(false); break;
                case 10: item->setVisible(false); break;
                case 11: item->setGeometry(3 * w, 2 * h, w, h); break;
                case 12: item->setGeometry(0 * w, 3 * h, w, h); break;
                case 13: item->setGeometry(1 * w, 3 * h, w, h); break;
                case 14: item->setGeometry(2 * w, 3 * h, w, h); break;
                case 15: item->setGeometry(3 * w, 3 * h, w, h); break;
                default: break;
            }
        }
    };

    auto strategy_d8 = [&]() {
        auto w = width() / 4;
        auto h = height() / 4;
        for(auto i = 0; i < mItems.size(); ++i) {
            auto item = mItems.at(i);
            switch(i) {
                case 0: item->setGeometry(0 * w, 0 * h, w * 3, h * 3); break;
                case 1: item->setVisible(false); break;
                case 2: item->setVisible(false); break;
                case 3: item->setGeometry(3 * w, 0 * h, w, h); break;
                case 4: item->setVisible(false); break;
                case 5: item->setVisible(false); break;
                case 6: item->setVisible(false); break;
                case 7: item->setGeometry(3 * w, 1 * h, w, h); break;
                case 8: item->setVisible(false); break;
                case 9: item->setVisible(false); break;
                case 10: item->setVisible(false); break;
                case 11: item->setGeometry(3 * w, 2 * h, w, h); break;
                case 12: item->setGeometry(0 * w, 3 * h, w, h); break;
                case 13: item->setGeometry(1 * w, 3 * h, w, h); break;
                case 14: item->setGeometry(2 * w, 3 * h, w, h); break;
                case 15: item->setGeometry(3 * w, 3 * h, w, h); break;
                default: break;
            }
        }
    };

    auto strategy_d4 = [&]() {
        auto w = width() / 4;
        auto h = height() / 4;
        for(auto i = 0; i < mItems.size(); ++i) {
            auto item = mItems.at(i);
            switch(i) {
                case 0: item->setGeometry(0 * w, 0 * h, w * 2, h * 2); break;
                case 1: item->setVisible(false); break;
                case 2: item->setGeometry(2 * w, 0 * h, w * 2, h * 2); break;
                case 3: item->setVisible(false); break;
                case 4: item->setVisible(false); break;
                case 5: item->setVisible(false); break;
                case 6: item->setVisible(false); break;
                case 7: item->setVisible(false); break;
                case 8: item->setGeometry(0 * w, 2 * h, w * 2, h * 2); break;
                case 9: item->setVisible(false); break;
                case 10: item->setGeometry(2 * w, 2 * h, w * 2, h * 2); break;
                case 11: item->setVisible(false); break;
                case 12: item->setVisible(false); break;
                case 13: item->setVisible(false); break;
                case 14: item->setVisible(false); break;
                case 15: item->setVisible(false); break;
                default: break;
            }
        }
    };

    auto strategy_d1 = [&]() {
        for(auto i = 0; i < mItems.size(); ++i) {
            auto item = mItems.at(i);
            switch(i) {
                case 0: item->setGeometry(0, 0, width(), height()); break;
                case 1: item->setVisible(false); break;
                case 2: item->setVisible(false); break;
                case 3: item->setVisible(false); break;
                case 4: item->setVisible(false); break;
                case 5: item->setVisible(false); break;
                case 6: item->setVisible(false); break;
                case 7: item->setVisible(false); break;
                case 8: item->setVisible(false); break;
                case 9: item->setVisible(false); break;
                case 10: item->setVisible(false); break;
                case 11: item->setVisible(false); break;
                case 12: item->setVisible(false); break;
                case 13: item->setVisible(false); break;
                case 14: item->setVisible(false); break;
                case 15: item->setVisible(false); break;
                default: break;
            }
        }
    };

    auto strategy_d0 = [&]() {
        for(auto &item: mItems) {
            if(item->fullScreen()) {
                item->setGeometry(0, 0, width(), height());
            } else {
                item->setVisible(false);
            }
        }
    };

    // 重置视图
    for(auto i = 0; i < mItems.size(); ++i) {
        auto &item = mItems.at(i);
        item->setVisible(true);
    }

    // 全屏策略
    auto fullCount = std::count_if(mItems.begin(), mItems.end(), [](const MonitorDeviderItem *item) { return item->fullScreen(); });
    if(fullCount) {
        strategy_d0();
        return;
    }

    // 根据分屏模式选择不同分屏策略
    switch(mMode) {
        case D16: {  // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

            strategy_d16();
            break;
        }
        case D13: {  // 0 1 2 3 4 5 7 8 11 12 13 14 15

            strategy_d13();
            break;
        }
        case D8: {  // 0 3 7 11 12 13 14 15

            strategy_d8();
            break;
        }
        case D4: {  // 0 2 8 10

            strategy_d4();
            break;
        }
        case D1: {  // 0

            strategy_d1();
            break;
        }
        default: break;
    }
}

void MonitorDeviderWidget::setMode(DeviderMode newMode) {
    mMode = newMode;

    // 重置视图选择状态
    for(auto &item: mItems) {
        item->setSelected(false);
        item->setFullScreen(false);
    }
    mItems.first()->setSelected(true);

    rebuild();
}

void MonitorDeviderWidget::nextSelectedItem() {
    static const QVector<int> d16_index {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
    static const QVector<int> d13_index {0, 1, 2, 3, 4, 5, 7, 8, 11, 12, 13, 14, 15};
    static const QVector<int> d8_index {0, 3, 7, 11, 12, 13, 14, 15};
    static const QVector<int> d4_index {0, 2, 8, 10};

    // 获取下标索引
    auto index = 0;
    for(auto i = 0; i < mItems.size(); ++i) {
        auto *item = mItems.at(i);
        if(item->selected()) {
            index = i;
            break;
        }
    }

    auto call_maping = [&items = mItems](int index /*元素当前位置*/, const QVector<int> &d_index) {  // 获取映射表索引
        auto temp = 0;
        for(auto i = 0; i < d_index.size(); i++) {
            if(d_index.at(i) == index) {
                temp = i;
            }
        }

        auto it = 0;
        if(temp + 1 > d_index.size() - 1) {
            it = 0;
        } else {
            it = d_index.at(temp + 1);
        }

        for(auto &item: items) {
            if(item == items.at(it)) {
                item->setSelected(true);
            } else {
                item->setSelected(false);
            }
        }
    };

    switch(mMode) {
        case D1: {
            break;
        }
        case D4: {
            call_maping(index, d4_index);
            break;
        }
        case D8: {
            call_maping(index, d8_index);
            break;
        }
        case D13: {
            call_maping(index, d13_index);
            break;
        }
        case D16: {
            call_maping(index, d16_index);
            break;
        }
        default: break;
    }
}
